import * as twgl from 'twgl.js'

const vs = `
#version 300 es
precision highp float;
out vec2 v_textureCoord;
void main() {
  float u = float(gl_VertexID % 2);
  float v = floor(float(gl_VertexID) / 2.0);
  v_textureCoord = vec2(u,v);
  gl_Position = vec4(-1.0 + u * 2.0,-1.0 + v * 2.0,0.0,1.0);
}
`
const fs = `
#version 300 es
precision highp float;
out vec4 out_FragColor;

uniform float minValue;
uniform float maxValue;
uniform sampler2D gridTex;
uniform sampler2D legendTex;
in vec2 v_textureCoord;

void main() {
  vec2 uv = v_textureCoord;
  float value = texture(gridTex,uv).r;
  float i = (value - minValue) / (maxValue - minValue);
  vec4 color = texture(legendTex,vec2(i,0.0));
  out_FragColor = color;
}
`

export const init = async (gl: WebGL2RenderingContext) => {
  twgl.addExtensionsToContext(gl)

  const programInfo = twgl.createProgramInfo(gl, [vs, fs])

  const arrays = {
    position: { numComponents: 1, data: new Uint8Array([0, 0, 0, 0]) },
  }

  const bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays)

  const gridData = await fetch(
    'http://test3d.hxgis.com/Assets/2025/SampleData/rain24h.json',
  ).then((response) => {
    return response.json()
  })

  let minValue = Number.POSITIVE_INFINITY
  let maxValue = Number.NEGATIVE_INFINITY
  const undefVal = gridData.undefVal
  const textureWidth = gridData.xNum
  const textureHeight = gridData.yNum
  const imageData = new Float32Array(textureWidth * textureHeight)
  for (let r = 0; r < textureHeight; r++) {
    for (let c = 0; c < textureWidth; c++) {
      const i = r * textureWidth + c
      const gridValue = gridData.grid[r][c]
      imageData[i] = gridValue

      if (undefVal !== gridValue) {
        if (minValue > gridValue) minValue = gridValue
        if (maxValue < gridValue) maxValue = gridValue
      }
    }
  }

  console.log(JSON.stringify({ minValue, maxValue }))

  const textures = twgl.createTextures(gl, {
    gridTex: {
      minMag: gl.LINEAR,
      wrapS: gl.CLAMP_TO_EDGE,
      wrapT: gl.CLAMP_TO_EDGE,
      height: textureHeight,
      width: textureWidth,
      format: gl.RED,
      internalFormat: gl.R32F,
      src: imageData,
      flipY: 1,
      auto: false,
    },
    legendTex: {
      minMag: gl.LINEAR,
      wrapS: gl.CLAMP_TO_EDGE,
      wrapT: gl.CLAMP_TO_EDGE,
      src: createLegend(),
    },
  })

  function render() {
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-ignore
    twgl.resizeCanvasToDisplaySize(gl.canvas)
    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height)

    const uniforms = {
      gridTex: textures.gridTex,
      legendTex: textures.legendTex,
      minValue,
      maxValue,
    }

    gl.useProgram(programInfo.program)
    twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo)
    twgl.setUniforms(programInfo, uniforms)
    twgl.drawBufferInfo(gl, bufferInfo, gl.TRIANGLE_STRIP)

    requestAnimationFrame(render)
  }
  requestAnimationFrame(render)
}

const createLegend = (): HTMLCanvasElement => {
  const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']
  const canvas = document.createElement('canvas')
  canvas.width = 64
  canvas.height = 1
  const ctx = canvas.getContext('2d')
  if (ctx) {
    const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0)
    for (let i = 0; i < colors.length; i++) {
      const percent = i / (colors.length - 1)
      gradient.addColorStop(percent, colors[i])
    }
    ctx.fillStyle = gradient
    ctx.clearRect(0, 0, canvas.width, canvas.height)
    ctx.fillRect(0, 0, canvas.width, canvas.height)
  }

  return canvas
}
